package com.frame.work.common.base.core;

import com.alibaba.fastjson.JSONObject;
import com.frame.work.common.constant.Const;
import com.frame.work.common.constant.Models;
import com.frame.work.common.constant.StringKey;

import com.frame.work.common.util.Time;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Component
public class CoreServer {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Value("${topic.rabbit.gatewayWriteChannel}")
    private String gatewayWriteChannel;

    //设置网关最后活跃时间
    public void setSocket(String socketKey, String mac, Jedis jedis) {
        //生成key
        String keyOfSocket = StringKey.getKeyOfSocket(socketKey);
        Map sockeMap = new HashMap<>(2);
        sockeMap.put("mac", mac);
        sockeMap.put("last_active_time", Time.NowTimeToSecond() + "");
        jedis.hmset(keyOfSocket, sockeMap);
    }

    //设置网关登陆时间
    public void setSocketLoginTime(String socketKey, Jedis jedis) {
        //生成key
        String keyOfSocket = StringKey.getKeyOfSocket(socketKey);
        //hash结构中若存在相应key才进行操作(hsetnx)
        jedis.hsetnx(keyOfSocket, "login_time", Time.NowTimeToSecond() + "");
    }

    //设置网关最后活跃时间
    public void setGateway(String deviceMac, String socketKey, Jedis jedis) {
        String keyOfGateway = StringKey.getKeyOfGateway(deviceMac);
        Map gatewayMessage = new HashMap(2);
        gatewayMessage.put("socket_key", socketKey);
        gatewayMessage.put("last_active_time", Time.NowTimeToSecond() + "");
        jedis.hmset(keyOfGateway, gatewayMessage);
        //同步网关
        syncGateway(deviceMac, jedis);
    }


    public void syncGateway(String mac, Jedis jedis) {
        Boolean shouldSync = false;
        String keyOfGateway = StringKey.getKeyOfGateway(mac);
        String last_sync_time = jedis.hget(keyOfGateway, "last_sync_time");
        if (StringUtils.isNotEmpty(last_sync_time)) {
            if (Time.NowTimeToSecond() - Long.parseLong(last_sync_time) > Const.SyncDeviceMinimalInterval.SYNY_DEVICE_MINIMAL_INTERVAL) {
                shouldSync = true;
            }
        } else {
            shouldSync = true;//这里可能有问题
        }
        if (shouldSync) {
            pushDeviceCreateOrUpdateToPersistenceList(Models.DEVICE_TYPE_GATEWAY, mac, Time.NowTimeToSecond(), jedis);
        }
    }

    /**
     * 将设备创建或更新推送到持久性列表
     */
    public void pushDeviceCreateOrUpdateToPersistenceList(Integer type, String mac, Long time, Jedis jedis) {
        Map data = new HashMap();
        data.put("type", type);
        data.put("mac", mac);
        data.put("time", time);
        String jsonString = JSONObject.toJSONString(data);
        pushDataToPersistenceList(type, jsonString, jedis);
    }

    public void pushDataToPersistenceList(Integer type, String jsonData, Jedis jedis) {
        Map data = new HashMap();
        data.put("type", type);
        data.put("data", jsonData);
        data.put("time", Time.NowTimeToSecond());
        String dataString = JSONObject.toJSONString(data);
        jedis.lpush(Const.RedisKey.KEY_GATEWAY_DATA_PERSISTENCE_LIST, dataString);
    }

    //设置网关登陆帧
    public void setGatewayLoginFrame(String gawtWayMac, String frameString, Jedis jedis) {
        String gateWayKey = StringKey.getKeyOfGateway(gawtWayMac);
        Map login_frame = new HashMap<>(1);
        login_frame.put("login_frame", frameString);
        jedis.hmset(gateWayKey, login_frame);
    }

    public void addGatewayToGatewaySet(String gateWayMac, Jedis jedis) {
        String keySet = StringKey.getKeyOfGatewaySet();
        jedis.sadd(keySet, gateWayMac);
        String keySortedSet = StringKey.getKeyOfGatewaySortedSet();
        jedis.zadd(keySortedSet, Time.NowTimeToSecond(), gateWayMac);
    }

    public void pushEventGatewayLoginToPersistenceList(String deviceMac, String socketKey, String frameString, Jedis jedis) {
        Map data = new HashMap(2);
        data.put("socket_key", socketKey);
        data.put("frame", frameString);
        String jsonStringData = JSONObject.toJSONString(data);
        pushEventToPersistenceList(Models.DEVICE_EVENT_TYPE_LOGIN, Models.DEVICE_TYPE_GATEWAY, deviceMac, jsonStringData, Time.NowTimeToSecond(), jedis);
    }

    public void pushEventToPersistenceList(Integer eventType, Integer deviceType, String deviceMac, String data, Long time, Jedis jedis) {
        Map modelData = new HashMap();
        modelData.put("type", eventType);
        modelData.put("device_type", deviceType);
        modelData.put("device_mac", deviceMac);
        modelData.put("data", data);
        modelData.put("create_time", time);
        String modelDataString = JSONObject.toJSONString(modelData);
        pushDataToPersistenceList(Const.DataPersistenceType.DATA_PERSISTENCE_TYPE_CREATE_DEVICE_EVENT, modelDataString, jedis);
    }

    public void writeDataToGateWay(String data, Object channel) {
        //rabbitMq Publish 命令用于将信息发送到指定的频道。
        Map<String, Object> frameAndChannel = new HashMap<>();
        frameAndChannel.put("frame", data);
        frameAndChannel.put("channelLongId", channel);
        rabbitTemplate.convertAndSend(gatewayWriteChannel, frameAndChannel);
    }

    private Map makeGatewayWriteDataMessage(String mac, String data) {
        Map map = new HashMap();
        map.put("type", Const.MESSAGE_TYPE_WRITE_DATA_TO_GATEWAY);
        map.put("mac", mac);
        map.put("data", data);
        map.put("time", Time.NowTimeToSecond());
        return map;
    }

    //设置网关状态
    public void setGatewayStatusFrame(String zigbeeMac, String frame, Jedis jedis) {
        String keyOfGateway = StringKey.getKeyOfGateway(zigbeeMac);
        Map statusFrame = new HashMap(1);
        statusFrame.put("status_frame", frame);
        jedis.hmset(keyOfGateway, statusFrame);
    }

    //把设备添加到网关中
    public void addDeviceToGatewayDeviceSet(String deviceMac, String gatewayMac, Jedis jedis) {
        String keySet = StringKey.getKeyOfGatewayDeviceSet(gatewayMac);
        jedis.sadd(keySet, deviceMac);
        String keySortedSet = StringKey.getKeyOfGatewayDeviceSortedSet(gatewayMac);
        jedis.zadd(keySortedSet, Time.NowTimeToSecond(), deviceMac);
    }


    public void setDevice(String deviceMac, String gatewayMac, String frameString, Jedis jedis) {
        String keyOfDevice = StringKey.getKeyOfDevice(deviceMac);
        Map map = new HashMap(3);
        map.put("gateway", gatewayMac);
        map.put("status_frame", frameString);
        map.put("last_active_time", Time.NowTimeToSecond().toString());
        jedis.hmset(keyOfDevice, map);
        syncGateWayDevice(deviceMac, jedis);
    }

    private void syncGateWayDevice(String deviceMac, Jedis jedis) {
        String key = StringKey.getKeyOfDevice(deviceMac);
        Boolean shouldSync = false;
        List<String> hmget = jedis.hmget(key, "last_sync_time", "gateway");
        String gatewayMac = null;
        if (hmget.size() > 0) {
            String lastSyncTime = hmget.get(0);
            gatewayMac = hmget.get(1);
            if (StringUtils.isNotEmpty(lastSyncTime)) {
                int i = Integer.parseInt(lastSyncTime, 10);
                if (Time.NowTimeToSecond() - i > Const.SyncDeviceMinimalInterval.SYNY_DEVICE_MINIMAL_INTERVAL) {
                    shouldSync = true;
                }
            } else {
                shouldSync = true;
            }
        }
        if (shouldSync) {
            if (StringUtils.isNotEmpty(gatewayMac)) {
                pushDeviceCreateOrUpdateToPersistenceList(Models.DEVICE_TYPE_GATEWAY_NODE, deviceMac, Time.NowTimeToSecond(), jedis);
            }

        }

    }
}
